home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / graphics / a-g / beyondthedark / developer / source / toaster / toaster.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-21  |  13.0 KB  |  528 lines

  1.  
  2. #include <exec/memory.h>
  3. #include <exec/execbase.h>
  4. #include <graphics/gfxbase.h>
  5. #include <intuition/intuitionbase.h>
  6. #include <libraries/iffparse.h>
  7. #include <utility/tagitem.h>
  8.  
  9. #define __USE_SYSBASE 42
  10.  
  11. #include <proto/exec.h>
  12. #include <proto/graphics.h>
  13. #include <proto/intuition.h>
  14. #include <proto/utility.h>
  15.  
  16. #include <string.h>
  17.  
  18. #include "btd.h"
  19.  
  20. struct GfxBase *GfxBase;
  21. struct IntuitionBase *IntuitionBase;
  22. struct Library *UtilityBase;
  23.  
  24. #define TPTAG(o) (BTD_Client+(o))
  25.  
  26. #define TP_Toasters TPTAG(0)
  27.  
  28. #define MAX_TOASTERS  20L
  29. #define DEF_TOASTERS   2L
  30.  
  31. #define NUM_IMAGES 4
  32.  
  33. #define IMAGE_WIDTH  64
  34. #define IMAGE_HEIGHT 64
  35. #define IMAGE_WIDBUF (IMAGE_WIDTH+20)
  36. #define IMAGE_HEIBUF (IMAGE_HEIGHT+20)
  37.  
  38. extern UBYTE *BytePackedFrames[];
  39.  
  40. #define ABS(x)   __builtin_abs(x)
  41. #define MIN(a,b) __builtin_min(a,b)
  42. #define MAX(a,b) __builtin_max(a,b)
  43.  
  44. #define NUM_COLORS 16
  45. #define NUM_PHASES ((NUM_IMAGES*2)-2)
  46.  
  47. struct BTDInteger ToasterIntParams[] =
  48.  {
  49.   TP_Toasters,"Toasters",BTDPT_INTEGER,DEF_TOASTERS,1L,MAX_TOASTERS,TRUE,
  50.  };
  51.  
  52. struct BTDNode *ToasterParams[] =
  53.  {
  54.   &ToasterIntParams[0].BI_Node,
  55.   NULL
  56.  };
  57.  
  58. struct BTDInfo ToasterInfo =
  59.  {
  60.   BTDI_Revision,MAKE_ID('T','O','S','T'),
  61.   "Toaster","The Must of Blankers","Markus Illenseer and Matthias Scheler",
  62.   ToasterParams
  63.  };
  64.  
  65. struct IToaster
  66.  {
  67.   LONG delay;
  68.   LONG x, y;
  69.   LONG old_x, old_y;
  70.   LONG xspeed, yspeed;
  71.   LONG phase;
  72.   LONG xcol, ycol;
  73.  };
  74.  
  75. struct Toasters /* structure for a swarm, including the wasp */
  76.  {
  77.   struct BTDDrawInfo *BTDDrawInfo;
  78.   WORD Width;   /* Width and */
  79.   WORD Height;  /* Height of the used area */
  80.   WORD NumToaster; /* total number of the Toasters*/
  81.   struct IToaster *Toasters;
  82.   struct PlanarImage *Images[NUM_PHASES];
  83.   LONG RandN,RandF,RandI;
  84.  };
  85.  
  86. UBYTE CMap[(NUM_COLORS-1)*3] =
  87.  {
  88.   0x33,0x33,0x33,0x55,0x55,0x55,0x88,0x55,0x22,0x66,0x66,0x66,0x77,0x77,0x44,
  89.   0x55,0x55,0x66,0xEE,0x55,0x22,0x88,0x88,0x88,0x99,0x99,0x99,0xBB,0xBB,0xBB,
  90.   0xCC,0xCC,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0xEE,0xEE,0xFF,0xFF,0xFF
  91.  };
  92.  
  93. struct PlanarImage
  94.  {
  95.   WORD pi_Width,pi_Height;
  96.   struct BitMap pi_BitMap;
  97.  };
  98.  
  99. /* library stuff */
  100.  
  101. char MyBlankerName[] = "toaster.btd";
  102. char MyBlankerID[]   = "Toaster Blanker V" VERSION "." REVISION " for BTD";
  103.  
  104. LONG MyBlankerLibInit(void)
  105.  
  106. {
  107.  if (GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",37L))
  108.   {
  109.    if (IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",37L))
  110.     {
  111.      if (UtilityBase=OpenLibrary("utility.library",37L)) return TRUE;
  112.  
  113.      CloseLibrary (&IntuitionBase->LibNode);
  114.     }
  115.    CloseLibrary (&GfxBase->LibNode);
  116.   }
  117.  return FALSE;
  118. }
  119.  
  120. void MyBlankerLibFree(void)
  121.  
  122. {
  123.  CloseLibrary (UtilityBase);
  124.  CloseLibrary (&IntuitionBase->LibNode);
  125.  CloseLibrary (&GfxBase->LibNode);
  126. }
  127.  
  128. /* random generator */
  129.  
  130. void __regargs InitRandom(struct Toasters *TP,ULONG Instance)
  131.  
  132. {
  133.  ULONG Time[2];
  134.  
  135.  CurrentTime (&Time[0],&Time[1]);
  136.  TP->RandN=(LONG)Time[0];
  137.  
  138.  if (Time[1]<1024L) Time[1]|=1;
  139.  else Time[1]>>=10;
  140.  Time[1]^=Instance;
  141.  
  142.  TP->RandF=4*Time[1]+1;
  143.  TP->RandI=2*Time[1]+1;
  144. }
  145.  
  146. WORD __regargs Random(struct Toasters *TP,WORD Max)
  147.  
  148. {
  149.  TP->RandN=TP->RandF*TP->RandN+TP->RandI;
  150.  if (TP->RandN<0L) TP->RandN=-TP->RandN;
  151.  
  152.  return (WORD)(TP->RandN%Max);
  153. }
  154.  
  155. /* implementation of library functions */
  156.  
  157. struct BTDInfo *QueryMyBlanker(void)
  158.  
  159. {
  160.  return &ToasterInfo;
  161. }
  162.  
  163. void __regargs DeletePlanarImage(struct PlanarImage *PI)
  164.  
  165. {
  166.  ULONG Index,Size;
  167.  
  168.  Size=PI->pi_BitMap.BytesPerRow*PI->pi_BitMap.Rows;
  169.  for (Index=0L; Index<PI->pi_BitMap.Depth; Index++)
  170.   FreeMem (PI->pi_BitMap.Planes[Index],Size);
  171.  
  172.  FreeVec (PI);
  173. }
  174.  
  175. struct PlanarImage __regargs *ConvertBytePacked(UBYTE *From,UWORD *RemapTab,
  176.                                                struct RastPort *RastPort)
  177.  
  178. {
  179.  struct PlanarImage *Target;
  180.  ULONG Index,Size;
  181.  LONG Depth,X,Y;
  182.  
  183.  if ((Target=AllocVec(sizeof(struct PlanarImage),MEMF_PUBLIC))==NULL) return NULL;
  184.  
  185.  Target->pi_Width=IMAGE_WIDTH;
  186.  Target->pi_Height=IMAGE_HEIGHT;
  187.  
  188.  Depth=1L;
  189.  for (Index=1L; Index<NUM_COLORS; Index++)
  190.   while (RemapTab[Index]>=(1L<<Depth)) Depth++;
  191.  
  192.  InitBitMap (&Target->pi_BitMap,Depth,Target->pi_Width,Target->pi_Height);
  193.  
  194.  Size=Target->pi_BitMap.BytesPerRow*Target->pi_BitMap.Rows;
  195.  for (Index=0L; Index<Target->pi_BitMap.Depth; Index++)
  196.   if ((Target->pi_BitMap.Planes[Index]=AllocMem(Size,MEMF_CHIP|MEMF_CLEAR))==NULL)
  197.    {
  198.     while (Index--) FreeMem (Target->pi_BitMap.Planes[Index],Size);
  199.     FreeVec (Target);
  200.     return NULL;
  201.    }
  202.  
  203.  RastPort->BitMap=&Target->pi_BitMap;
  204.  
  205.  if (GfxBase->LibNode.lib_Version>=40)
  206.   {
  207.    ULONG Pixels;
  208.    UBYTE *Data;
  209.  
  210.    Pixels=Target->pi_Width*Target->pi_Height;
  211.    if (Data=AllocVec(Pixels,MEMF_PUBLIC))
  212.     {
  213.      UBYTE *To,Nibble;
  214.  
  215.      To=Data;
  216.      while (Pixels)
  217.       {
  218.        Nibble=*From>>4;
  219.        if (Nibble) *To++=RemapTab[Nibble];
  220.        else *To++=BTD_BgPen;
  221.  
  222.        Nibble=(*From++)&15;
  223.        if (Nibble) *To++=RemapTab[Nibble];
  224.        else *To++=BTD_BgPen;
  225.  
  226.        Pixels-=2L;
  227.       }
  228.      WriteChunkyPixels (RastPort,0,0,Target->pi_Width-1,Target->pi_Height-1,Data,IMAGE_WIDTH);
  229.  
  230.      FreeVec (Data);
  231.      return Target;
  232.     }
  233.   }
  234.  
  235.  for (Y=0L; Y<Target->pi_Height; Y++)
  236.   for (X=0L; X<Target->pi_Width; X+=2)
  237.    {
  238.     UBYTE Nibble;
  239.  
  240.     Nibble=*From>>4;
  241.     if (Nibble)
  242.      {       SetAPen (RastPort,RemapTab[Nibble]);
  243.       (void)WritePixel(RastPort,X,Y);
  244.      }
  245.  
  246.     Nibble=(*From++)&15;
  247.     if (Nibble)
  248.      {       SetAPen (RastPort,RemapTab[Nibble]);
  249.       (void)WritePixel(RastPort,X+1,Y);
  250.      }
  251.    } 
  252.  
  253.  return Target;
  254. }
  255.  
  256. void __regargs SafeEraseRect(struct BTDDrawInfo *BTDDrawInfo,
  257.                              LONG Left,LONG Top,
  258.                              LONG Right,LONG Bottom)
  259.  
  260. {
  261.  if ((Left<BTDDrawInfo->BDI_Width)&&(Right>=MAX(Left,0L))&&
  262.      (Top<BTDDrawInfo->BDI_Height)&&(Bottom>=MAX(Top,0L)))
  263.   EraseRect (BTDDrawInfo->BDI_RPort,
  264.              BTDDrawInfo->BDI_Left+MAX(Left,0L),
  265.              BTDDrawInfo->BDI_Top+MAX(Top,0L),
  266.              BTDDrawInfo->BDI_Left+MIN(Right,BTDDrawInfo->BDI_Width-1),
  267.              BTDDrawInfo->BDI_Top+MIN(Bottom,BTDDrawInfo->BDI_Height-1));
  268. }
  269.  
  270. void __regargs DrawPlanarImage(struct BTDDrawInfo *BTDDrawInfo,
  271.                                struct PlanarImage *PI,
  272.                                LONG XPos,LONG YPos)
  273.  
  274. {
  275.  LONG Left,Top,Right,Bottom;
  276.  
  277.  Left=MAX(XPos,0L);
  278.  Top=MAX(YPos,0L);
  279.  Right=MIN(XPos+PI->pi_Width,BTDDrawInfo->BDI_Width);
  280.  Bottom=MIN(YPos+PI->pi_Height,BTDDrawInfo->BDI_Height);
  281.  
  282.  if ((Left<Right)&&(Top<Bottom))
  283.   BltBitMapRastPort (&PI->pi_BitMap,Left-XPos,Top-YPos,
  284.                      BTDDrawInfo->BDI_RPort,Left,Top,
  285.                      Right-Left,Bottom-Top,0xC0);
  286. }
  287.  
  288. LONG __regargs TestExtent(struct Toasters *TP,LONG Start,LONG Me,LONG x,LONG y)
  289.  
  290. {
  291.  LONG Index;
  292.   
  293.  for (Index=Start; Index<TP->NumToaster; Index++)
  294.   if ((Index!=Me)&&!TP->Toasters[Index].delay&&
  295.       (ABS(x-TP->Toasters[Index].x)<IMAGE_WIDBUF)&&
  296.       (ABS(y-TP->Toasters[Index].y)<IMAGE_HEIBUF)) return Index;
  297.   
  298.  return -1L;
  299. }
  300.  
  301. BOOL __regargs FindLaunchPos(struct Toasters *TP,LONG Index)
  302.  
  303. {
  304.  LONG x,y;
  305.   
  306.  x=TP->Width-IMAGE_WIDTH;
  307.  y=IMAGE_HEIGHT+Random(TP,TP->Height);
  308.   
  309.  FOREVER
  310.   {
  311.    if (x<=(2*IMAGE_WIDTH)) return FALSE;
  312.     
  313.    if (TestExtent(TP,0,Index,x,y)==-1L)
  314.     {
  315.      TP->Toasters[Index].x=TP->Toasters[Index].old_x=x;
  316.      TP->Toasters[Index].y=TP->Toasters[Index].old_y=y;
  317.      TP->Toasters[Index].xspeed=Random(TP,3)+1;
  318.      TP->Toasters[Index].yspeed=Random(TP,2)+1;
  319.      TP->Toasters[Index].phase=Random(TP,NUM_IMAGES);
  320.  
  321.      return TRUE;
  322.     }
  323.     
  324.    if (y>(-IMAGE_HEIGHT)) y-=IMAGE_HEIGHT;
  325.    else x-=IMAGE_WIDTH;
  326.   }
  327. }
  328.  
  329. LONG __regargs ActXSpeed(struct Toasters *TP,LONG Index)
  330.  
  331. {
  332.  if (TP->Toasters[Index].xcol==-1L) return TP->Toasters[Index].xspeed;
  333.  else return ActXSpeed(TP,TP->Toasters[Index].xcol);
  334. }
  335.  
  336. LONG __regargs ActYSpeed(struct Toasters *TP,LONG Index)
  337.  
  338. {
  339.  if (TP->Toasters[Index].ycol==-1L) return TP->Toasters[Index].yspeed;
  340.  else return ActXSpeed(TP,TP->Toasters[Index].ycol);
  341. }
  342.  
  343. struct Toasters *InitMyBlanker(struct TagItem *TagList)
  344.  
  345. {
  346.  struct BTDDrawInfo *BTDDrawInfo;
  347.  ULONG *Error,Dummy,Instance,Index;
  348.  LONG NumToaster;
  349.  struct Toasters *TP;
  350.  struct RastPort TempRastPort;
  351.  UBYTE *CMapPtr;
  352.  
  353.  if ((BTDDrawInfo=(struct BTDDrawInfo *)
  354.                    GetTagData(BTD_DrawInfo,NULL,TagList))==NULL) return NULL;
  355.  Error=(ULONG *)GetTagData(BTD_Error,(ULONG)&Dummy,TagList);
  356.  
  357.  Instance=GetTagData(BTD_Instance,0L,TagList);
  358.  NumToaster=GetTagData(TP_Toasters,DEF_TOASTERS,TagList);
  359.  
  360.  if ((TP=AllocVec(sizeof(struct Toasters),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  361.   {
  362.    *Error=BTDERR_Memory;
  363.    return NULL;
  364.   }
  365.  
  366.  if ((TP->Toasters=AllocVec(sizeof(struct IToaster)*NumToaster,MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  367.   {
  368.    FreeVec (TP);
  369.  
  370.    *Error=BTDERR_Memory;
  371.    return NULL;
  372.   }
  373.  
  374.  InitRastPort (&TempRastPort);
  375.  for (Index=0L; Index<NUM_IMAGES; Index++)
  376.   if ((TP->Images[Index]=ConvertBytePacked(BytePackedFrames[Index],
  377.                                            BTDDrawInfo->BDI_Pens-1,
  378.                                            &TempRastPort))==NULL)
  379.    {
  380.     while (Index--) FreeVec (TP->Images[Index]);
  381.     FreeVec (TP->Toasters);
  382.     FreeVec (TP);
  383.  
  384.     *Error=BTDERR_Memory;
  385.     return NULL;
  386.    }
  387.  for (; Index<NUM_PHASES; Index++)
  388.   TP->Images[Index]=TP->Images[NUM_PHASES-Index];
  389.  
  390.  TP->BTDDrawInfo=BTDDrawInfo;
  391.  TP->Width=BTDDrawInfo->BDI_Width;
  392.  TP->Height=BTDDrawInfo->BDI_Height;
  393.  TP->NumToaster=NumToaster;
  394.  
  395.  InitRandom (TP,Instance);
  396.  
  397.  for (Index=0L, CMapPtr=CMap; Index<(NUM_COLORS-1L); Index++)
  398.   {
  399.    BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  400.    BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  401.    BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=*CMapPtr++;
  402.    BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  403.   }
  404.  
  405.  for (Index=0L; Index<NumToaster; Index++)
  406.   if (!FindLaunchPos(TP,Index)) TP->Toasters[Index].delay=30;
  407.  
  408.  return TP;
  409. }
  410.  
  411. void EndMyBlanker(struct Toasters *TP)
  412.  
  413. {
  414.  ULONG Index;
  415.  
  416.  for (Index=0L; Index<NUM_IMAGES; Index++) DeletePlanarImage (TP->Images[Index]);
  417.  FreeVec (TP->Toasters);
  418.  FreeVec (TP);
  419. }
  420.  
  421. void AnimMyBlanker(struct Toasters *TP)
  422.  
  423. {
  424.  struct BTDDrawInfo *BTDDrawInfo;
  425.  LONG i,j;
  426.  
  427.  BTDDrawInfo=TP->BTDDrawInfo;
  428.  
  429.  for (i=0; i<TP->NumToaster; i++)
  430.   if (TP->Toasters[i].delay==0L)
  431.    {
  432.     TP->Toasters[i].old_x=TP->Toasters[i].x;
  433.     TP->Toasters[i].old_y=TP->Toasters[i].y;
  434.     TP->Toasters[i].x-=TP->Toasters[i].xspeed;
  435.     TP->Toasters[i].y+=TP->Toasters[i].yspeed;
  436.     TP->Toasters[i].xcol=-1;
  437.     TP->Toasters[i].ycol=-1;
  438.    }
  439.  
  440.  for (i=0; i<TP->NumToaster; i++)
  441.   {
  442.    if (TP->Toasters[i].delay==0L)
  443.     {
  444.      j=-1;
  445.      while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
  446.       {
  447.        if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
  448.         {
  449.          if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].ycol=j;
  450.          if (TP->Toasters[i].xspeed==TP->Toasters[j].xspeed) TP->Toasters[i].xspeed++;
  451.         }
  452.        else
  453.         {
  454.          if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
  455.          if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
  456.         }
  457.        if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
  458.         {
  459.          if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].xcol=j;
  460.          if (TP->Toasters[i].yspeed==TP->Toasters[j].yspeed) TP->Toasters[i].yspeed++;
  461.         }
  462.       }
  463.     }
  464.   }
  465.  
  466.  for (i=0; i<TP->NumToaster; i++)
  467.   {
  468.    if (TP->Toasters[i].delay==0L)
  469.     {
  470.      TP->Toasters[i].x=TP->Toasters[i].old_x-ActXSpeed(TP,i);
  471.      TP->Toasters[i].y=TP->Toasters[i].old_y + ActYSpeed(TP,i);
  472.     }
  473.   }
  474.           
  475.  for (i=0; i<TP->NumToaster; i++)
  476.   {
  477.    if (TP->Toasters[i].delay==0L)
  478.     {
  479.      j=-1;
  480.      while ((j=TestExtent(TP,j+1,i,TP->Toasters[i].x,TP->Toasters[i].y))>=0)
  481.       {
  482.        if (ABS(TP->Toasters[j].old_x-TP->Toasters[i].old_x)<(IMAGE_WIDBUF))
  483.         if (TP->Toasters[i].x > TP->Toasters[j].x) TP->Toasters[i].x=TP->Toasters[i].old_x;
  484.         else
  485.          if (TP->Toasters[i].y<TP->Toasters[j].y) TP->Toasters[i].y=TP->Toasters[i].old_y;
  486.  
  487.        if (ABS(TP->Toasters[j].old_y-TP->Toasters[i].old_y)<(IMAGE_HEIBUF))
  488.         if (TP->Toasters[i].y<TP->Toasters[j].y)
  489.          TP->Toasters[i].y=TP->Toasters[i].old_y;
  490.       }
  491.     }
  492.   }
  493.  
  494.  for (i=0; i<TP->NumToaster; i++)
  495.   if (TP->Toasters[i].delay==0L)
  496.    {
  497.     TP->Toasters[i].phase=(TP->Toasters[i].phase+1)%NUM_PHASES;
  498.  
  499.     SafeEraseRect (BTDDrawInfo,
  500.                    TP->Toasters[i].x+IMAGE_WIDTH,
  501.                    TP->Toasters[i].old_y,
  502.                    TP->Toasters[i].x+IMAGE_WIDTH+TP->Toasters[i].xspeed,
  503.                    TP->Toasters[i].old_y+IMAGE_HEIGHT);
  504.     SafeEraseRect (BTDDrawInfo,
  505.                    TP->Toasters[i].old_x,
  506.                    TP->Toasters[i].old_y,
  507.                    TP->Toasters[i].old_x+IMAGE_WIDTH,
  508.                    TP->Toasters[i].old_y+TP->Toasters[i].yspeed);
  509.  
  510.     DrawPlanarImage (BTDDrawInfo,TP->Images[TP->Toasters[i].phase],
  511.                      TP->Toasters[i].x,TP->Toasters[i].y);
  512.  
  513.     if ((TP->Toasters[i].x<=(-IMAGE_WIDTH-1))||
  514.         (TP->Toasters[i].y>=TP->Height)) TP->Toasters[i].delay=Random(TP,50);
  515.    }
  516.   else
  517.    if (--TP->Toasters[i].delay==0L)
  518.     TP->Toasters[i].delay=FindLaunchPos(TP,i)?0:30;
  519.  
  520.  WaitTOF();
  521. }
  522.  
  523. ULONG PenCountMyBlanker(struct TagItem *TagList)
  524.  
  525. {
  526.  return NUM_COLORS-1L;
  527. }
  528.